// File:			R4.cpp
// Authors:			Richard Burris, Joshua Douty
// Purpose:			R4 work file
// Version:        	6.0
// Date:			11/03/2011


#include "mpx_supt.h"
//#include "R1.h"
#include "R2.h"
#include "R3.h"
#include "R4.h"
#include "R6.h"
//#include "COMHAND.h"

extern PCB_Pointer CurrOP;
extern PCB_Pointer Ready;
extern PCB_Pointer Blocked;

/*	Procedure:  load
	Purpose: Either calls the load helpfile, or calls the loader function
	Parameters:	char* param: contains the filename
				char arg: determines whether to find the helpfile, or to run the command
	Return value: void
	Calls: 	readHelp 
			loader
	Globals: none
	Errors: none
*/
void load(char* param, char arg){
	if (arg == '?') {	
		readHelp("load2.txt");
		
	} else if (arg == '*') {
		int thePrio = 0;
		//char* fileNam = "\0\0\0\0\0\0\0\0\0\0\0";
		char* fileNam = strtok(param," "); //pull the filename, delimit by a space
		thePrio = atoi(strtok(NULL, " "));//pull the priority number if applicable
		int length  = strlen(fileNam);
		fileNam[length] = '\0';
		fileNam[length+1] = '\0';
		loader(fileNam, thePrio);
	}//end else
}//end load

void load2(char*param, int thePrio){
		char* fileNam = strtok(param," "); //pull the filename, delimit by a space
		int length  = strlen(fileNam);
		fileNam[length] = '\0';
		fileNam[length+1] = '\0';
		loader(fileNam, thePrio);

}//end load2

/*	Procedure:  loader
	Purpose: loads a single .mpx file as a process
	Parameters:	char* fName: The name of the file to load as a process
				int priorityy: The priority of the process to be loaded.  Defaulted as 0
	Return value: idv
	Calls: 	findPCB
			createPCB2
	Globals: none
	Errors: ERR_SUP_NAMLNG - path name too long
			ERR_SUP_FILNFD - FIle not found
			ERR_SUP_FILINV - Invalid file
			ERR_SUP_LDADDR - Invalid load address
			ERR_SUP_LDFAIL - Load failed
			ERR_SUP_PROGSZ - Program too large to fit into memory
*/
void loader(char *fName, int priorityy){
	int err;
	int PCB_length;
	int PCB_start_offset;
	PCB_Pointer newProc;
	context_Pointer newCon;
	int loadError;
	int length = strlen(fName);
	fName[length] = '\0';
	
	//check the arguments	
		//check that the priority is valid
		if ((priorityy>127)||(priorityy < (-128))){
			printf("Invalid priority, program not loaded\n");
			return;
		}
		
		//check that the process name is unique
		else if (findPCB(fName) != NULL){
			printf("\nA process already exists with this name, program not loaded\n");
			return;
		}
		else{
	
			err = sys_check_program("\0", fName, &PCB_length, &PCB_start_offset);
			switch(err){
				case ERR_SUP_NAMLNG:{
					printf("Pathname is too long, program not loaded\n");
					break;
				} 
				case ERR_SUP_FILNFD:{
					printf("File not found, program not loaded\n");
					break;
				} 
				case ERR_SUP_FILINV:{
					printf("File is invalid, program not loaded\n");	
					break;
				} 
				case OK:{
		
					newProc = createPCB2(fName, SYSTEM, priorityy); //create a PCB with this stuff
					newProc->stateR = READY;								//set it to ready, and unsuspendsed
					newProc->stateS = NOTSUSPEND;

					newProc->memSize = PCB_length;
					newProc->loadAddr = (unsigned char*)sys_alloc_mem(PCB_length);
					newProc->executeAddr = PCB_start_offset +(newProc->loadAddr);
					//newProc->  ;
					newCon = (context*)newProc->sTop;
					newCon->IP = FP_OFF(newProc->executeAddr) ;
					newCon->CS = FP_SEG(newProc->executeAddr) ;
					newCon->DS = _DS;
					newCon->ES = _ES;
					newCon->FLAGS = 0x200;	

					loadError =sys_load_program((void*)(newProc->loadAddr), newProc->memSize, "\0", fName);

					switch(loadError){
						case OK:{
							suspendPCB(fName, '*');//since the PCB is already placed in the ready (and resumed) queue whenever it is created, we must suspend it					
							break;
						} 
						case ERR_SUP_FILINV:{
							deletePCB2(newProc);
							printf("Invalid File, Program not loaded\n");
							break;
						} 
						case ERR_SUP_FILNFD:{
							deletePCB2(newProc);
							printf("File not Found, Program not loaded\n");
							break;
						} 
						case ERR_SUP_LDADDR:{
							deletePCB2(newProc);
							printf("Invalid Load Address, Program not loaded\n");
							break;
						} 
						case ERR_SUP_LDFAIL:{
							deletePCB2(newProc);
							printf("Load Failed\n");
							break;
						} 
						case ERR_SUP_NAMLNG:{
							deletePCB2(newProc);
							printf("File Name too large\n");
							break;
						} 
						case ERR_SUP_PROGSZ:{
							deletePCB2(newProc);
							printf("Program is too large to fit into memory\n");
							break;
						}
					}//end switch loadError
				break;
			}//end case OK for switch(err)
		}//end switch err
	}//end else	
}//end loader()



/*	Procedure:  loadIDLE
	Purpose: loads a single .mpx file as a process
	Parameters:	NONE
	Return value: 
	Calls: 	loader
	Globals: none
	Errors: ERR_SUP_NAMLNG - path name too long
			ERR_SUP_FILNFD - FIle not found
			ERR_SUP_FILINV - Invalid file
			ERR_SUP_LDADDR - Invalid load address
			ERR_SUP_LDFAIL - Load failed
			ERR_SUP_PROGSZ - Program too large to fit into memory
*/
void loadIDLE(){
char* idlename = "IDLE";
idlename[4] = '\0';
load2(idlename, -128);

	
}//end loadIDLE

/*	Procedure:  kill
	Purpose: terminates a application class PCB
	Parameters:	char* param: contains the filename
				char arg: determines whether to find the helpfile, or to run the command
	Return value: int: determines if successful
	Calls: 	readHelp 
			findPCB
			deletePCB2
	Globals: none
	Errors: none
*/
void kill(char *param, char arg){//must terminate a process
	if(arg == '?'){
		readHelp("termin.txt");
	}else if (arg == '*'){
		PCB_Pointer badPro = findPCB(param);
		
		if (badPro!=NULL){//if it is found, proceed to remove it
			if(badPro->clas !=SYSTEM){// if it isn't a system process, remove it
				deletePCB2(badPro);//removes it form the queue, deletes it, and freese its memory
			}else  printf("\n This is a system process, termination aborted.\n");
		}else printf("Process name not found, try again");
	}
}//end kill


